/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.game.math.view.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Observable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.game.math.view.expression.Operator;

/**
 *
 * @author nmduc
 */
class Configure extends Observable {

  private var operators:Set[Enumeration#Value] = Set();
  private var temProperties:Properties = null;
  private var properties:Properties = new Properties();
  try {
    var f:File = new File(Configure.CONFIG_FILE_NAME);
    if (f.exists()) {
      properties.load(new FileInputStream(f));
    }
  } catch {case ex:IOException =>
      Logger.getLogger(Configure.getClass().getName()).log(Level.SEVERE, null, ex);
  } finally {
    if (this.properties.getProperty(Configure.SIGN) == null) {
      this.properties.setProperty(Configure.SIGN, "false");
    }
    if (this.properties.getProperty(Configure.NUM_LENGTH) == null) {
      this.properties.setProperty(Configure.NUM_LENGTH, "1");
    }
    if (this.properties.getProperty(Configure.NUM_EXPRESSION) == null) {
      properties.setProperty(Configure.NUM_EXPRESSION, "10");
    }
    if (this.properties.getProperty(Configure.NUM_OPERATOR) == null) {
      this.properties.setProperty(Configure.NUM_OPERATOR, "1");
    }
    if (this.properties.getProperty(Configure.OPERATORS) == null) {
      this.properties.setProperty(Configure.OPERATORS, Operator.ADD.toString());
    }
    if (this.properties.getProperty(Configure.MULTIPLIED_TABLE) == null) {
      this.properties.setProperty(Configure.MULTIPLIED_TABLE, "false");
    }
    if (this.properties.getProperty(Configure.MULTIPLIED_NUMBER) == null) {
      this.properties.setProperty(Configure.MULTIPLIED_NUMBER, "1");
    }
    operators = Set();
    var currentOperators:String = this.properties.getProperty(Configure.OPERATORS);
    var operatorNames:Array[String] = currentOperators.split("\\|");
    for (operatorName <- operatorNames) {
      if (!operatorName.isEmpty()) {
        operators += Operator.withName(operatorName);
      }
    }
  }

  def save():Unit = {
    try {
      //Store operator list to String
      var operatorString:StringBuilder = new StringBuilder();
      operatorString.append(operators.mkString("|"));
//      for (operator <- operators) {
//        operatorString.append(operator.toString()).append("|");
//      }
      this.properties.setProperty(Configure.OPERATORS, operatorString.toString());
      this.properties.store(new FileOutputStream(Configure.CONFIG_FILE_NAME), "");
    } catch {case  ex:IOException =>
      Logger.getLogger(Configure.getClass().getName()).log(Level.SEVERE, null, ex);
    }
  }

  def getProperty(key:String):String= {
    this.properties.getProperty(key);
  }

  def setProperty(key:String, value:String):Any = {
    this.properties.setProperty(key, value);
  }

  def addOperator(operator:Enumeration#Value):Unit = {
    operators += operator;
    this.setChanged();
    this.notifyObservers();
  }

  def removeOperator(operator:Enumeration#Value):Unit = {
    operators -= (operator);
    this.setChanged();
    this.notifyObservers();
  }

  def  getOperators():Set[Enumeration#Value] = {
    operators;
  }

  def isChosenMultiTable():Boolean = {
    this.getProperty(Configure.MULTIPLIED_TABLE).toBoolean;
  }

  def setChosenMultiTable(choosen:Boolean , multipliedNumber:Int):Unit = {
    this.properties.setProperty(Configure.MULTIPLIED_TABLE, choosen.toString());
    this.properties.setProperty(Configure.MULTIPLIED_NUMBER, Integer.toString(multipliedNumber));
    this.setChanged();
    this.notifyObservers();
  }

  def getChosenMultiNumber():Int = {
    this.properties.getProperty(Configure.MULTIPLIED_NUMBER).toInt;
  }

  def initializeTempProperties():Unit = {
    this.temProperties = this.properties.clone().asInstanceOf[Properties];
  }

  def getTempProperties():Properties = {
    this.temProperties;
  }

  def removeTempProperties():Unit = {
    this.temProperties = null;
  }

  def updateByTempProperties():Unit = {
    if (this.temProperties != null) {
      this.properties.clear();
      this.properties.putAll(this.temProperties);
    } else {
      throw new NullPointerException("temProperties is not initialized yet.");
    }
  }
}

object Configure {
  val SIGN:String = "sign";
  val NUM_LENGTH:String = "num.length";
  val NUM_EXPRESSION:String = "num.expression";
  val NUM_OPERATOR:String = "num.operator";
  val OPERATORS:String = "operators";
  val MULTIPLIED_TABLE:String = "mult.table";
  val MULTIPLIED_NUMBER:String = "mult.number";
  val CONFIG_FILE_NAME:String = "config.properties";
  val configure:Configure = new Configure();
  def getInstance():Configure = {
    Configure.configure;
  }
}